#include <fstream>
#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "../comm/httplib.h"
#include "OJ_control.hpp"

using namespace std;
using namespace httplib;
using namespace ns_control;

static Control *ctrl_ptr = nullptr;

void Recovery(int signo)
{
        ctrl_ptr->RecoveryMachine();
}

int main()
{
        // 0、修改指定信号的默认行为，把ctrl + \产生的SIGQUIT信号重定向为一键上线所有主机（交由运维使用）
        signal(SIGQUIT, Recovery);

        // 1、守护进程化
        if (daemon(1, 0) == -1)
        {
                perror("oj_server 守护进程化失败！\n");
                exit(EXIT_FAILURE);
        }

        // 2、用户请求的服务路由功能（用户不同的请求前往不同的区域）
        Server svr;   // httplib中的Server类
        Control ctrl; // 核心业务逻辑的控制器（初始化的同时，加载题库）
        ctrl_ptr = &ctrl;

        // 3、搭建首页，告诉httplib服务器使用指定的目录作为静态文件服务的根目录，在找不到任何对应路由请求的情况下，使用这个目录下的文件作为响应（即首页文件）
        svr.set_base_dir("./wwwroot");

        // 3.1 获取所有题目的列表
        svr.Get("/all_questions", [&ctrl](const Request &req, Response &resp)
                { 
                string html;
                ctrl.AllQuestions(&html);
                resp.set_content(html, "text/html; charset=utf-8"); });

        // 3.2 用户提供题目编号来获取题目内容
        svr.Get(R"(/question/(\d+))", [&ctrl](const Request &req, Response &resp)
                {
                string number = req.matches[1];     //matches[1]中储存着正则匹配到的字符
                string html;
                ctrl.OneQuestion(number, &html);
                resp.set_content(html, "text/html; charset=utf-8"); });

        // 3.3 用户提交代码，使用我们的判题功能
        svr.Post(R"(/judge/(\d+))", [&ctrl](const Request &req, Response &resp)
                 {   string number = req.matches[1];
                 string result_json;
                 ctrl.Judge(number, req.body, &result_json);
                 resp.set_content(result_json, "application/json;charset=utf-8"); });

        svr.listen("0.0.0.0", 8080);
        return 0;
}